package org.interfaceadaptation.parameter.expression.impl;

import java.beans.PropertyDescriptor;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import org.interfaceadaptation.parameter.expression.Context;
import org.interfaceadaptation.parameter.expression.Expression;
import org.interfaceadaptation.util.ReflectionUtils;

public abstract class AbstractProperty extends AbstractExpression {

	protected PropertyDescriptor propertyDescriptor;

	public AbstractProperty(Expression parent) {
		super(parent);
	}

	public PropertyDescriptor getPropertyDescriptor() {
		return propertyDescriptor;
	}

	public Class<?> getReturnType() {
		return propertyDescriptor.getReadMethod().getReturnType();
	}

	public Class<?> getGenericReturnType() {
		if (Collection.class.isAssignableFrom(getReturnType())) {
			ParameterizedType stringListType = (ParameterizedType) propertyDescriptor
					.getReadMethod().getGenericReturnType();
			return (Class<?>) stringListType.getActualTypeArguments()[0];
		} else {
			return null;
		}
	}
	
	
	@Override
	public PropertyContext createExpressionContext(Context context) {
		return new PropertyContext(this);
	}
	
	@Override
	public Object getValue(Context context) {
		Object base = getParent().getValue(context);
		return ReflectionUtils.invokePropertyGetter(propertyDescriptor,base);
	}

	@Override
	public void setValue(Context context, Object value) {
		Object target = getParent().getValue(context);
		ReflectionUtils.invokePropertySetter(propertyDescriptor,target, value);
		
	}

	@Override
	public String toString() {
		return getPath();
	}
	
	@Override
	public String getDefaultNodeName() {
		 return propertyDescriptor.getName();
	}
	
}